'''
Created on May 16, 2010

@author: roni
'''
from ns2Scenario import Ns2Scenario
import random
import logging
from projectConstants import ProjectConstants
import networkx

class RandomScenario(object):
    '''
    Generates a random BA-model network
    '''

    def generate(self,nodes,added_edges,generators):
        new_graph = networkx.generators.random_graphs.barabasi_albert_graph(nodes,added_edges)
        
        scenario = Ns2Scenario()
        for node in new_graph.nodes():            
            scenario.add_node()
               
        for node in new_graph.nodes():
            for neighbor in new_graph.neighbors(node):                                
                # TODO: think if should add a bidirectional edge or not
                scenario.add_edge(node, neighbor, Ns2Scenario.LINK_DELAY)
                scenario.add_edge(neighbor, node, Ns2Scenario.LINK_DELAY)
        
        # Choose random pairs from the set of nodes, preferring nodes with low degree (heuristic for not being on a path)
        logging.info("Choosing agents...")        
        candidates = []
        for min_degree in xrange(added_edges,nodes+1):
            for node in new_graph.nodes():
                if new_graph.degree(node)==min_degree:
                    candidates.append(node)
            num_of_candidates = len(candidates)
            # If there aren't enough pairs to make different generators - continue
            if (num_of_candidates-1)*num_of_candidates>generators:
                break
                
        used_pairs = set()
        relevant_nodes = len(candidates)   
        while len(used_pairs)<generators: 
            source_index = random.randint(0,relevant_nodes-1)
            source = candidates[source_index]
            target_index = random.randint(0,relevant_nodes-1)
            while target_index==source_index:
                target_index = random.randint(0,relevant_nodes-1)
            target = candidates[target_index]
            pair = (source,target)
            if pair not in used_pairs:  
                logging.info("Added pair (%s->%s)" % pair)               
                scenario.add_agent(source, target)
                used_pairs.add(pair)
        
        scenario.simulate()
        return scenario        
        
        